home *** CD-ROM | disk | FTP | other *** search
/ Shareware Grab Bag / Shareware Grab Bag.iso / 007 / pctekap1.arc / TURBOIO.ARC / ANSISTUF.INC next >
Text File  |  1985-08-17  |  24KB  |  867 lines

  1. (*
  2.                           AnsiStuf.inc
  3.   
  4.  
  5.     Dedicated to the public domain.
  6.                 -- Cole Brecheen
  7.                    17 August 1985
  8. *)
  9.  
  10. {$U-,C-,R-}{Enables keyboard buffering.}
  11. {$V-} {Relaxes type checking on string parameters.}
  12. {Depends on Dos2io-1.inc and Dos2io-2.inc.}
  13.  
  14. CONST
  15.   GrafBdAddr = $B800; {segment address of color/graphics memory}
  16.   MonoBdAddr = $B000; {segment address of memory on mono board}
  17.   UnderCode = 'U';
  18.   BoldCode = 'B';
  19.   FlashCode = 'F';
  20.   ReverseCode = 'R';
  21.   PlainCode = 'P';
  22.  
  23. TYPE
  24.   RegisterRecord = {record type used with Turbo's msdos function}
  25.     RECORD
  26.       case BOOLEAN of
  27.     TRUE : (ax,bx,cx,dx,bp,si,di,ds,es,flags: INTEGER);
  28.     FALSE: (al,ah,bl,bh,cl,ch,dl,dh     : BYTE);
  29.       END;
  30.  
  31.   sc_TextAttribute = ( plain, bold, underscored, blinking,
  32.                ReverseVideo, invisible );
  33.   sc_ScreenMode    = ( BW40x25, color40x25, BW80x25, color80x25,
  34.                color320, BW320, BW640, WrapAtEndOfLine );
  35.   sc_AttributeSet  = set of sc_TextAttribute;
  36.  
  37.   VideoMethods = ( ANSI, ROM, DMA );
  38.  
  39.   VideoMemChar = record
  40.            case boolean of
  41.              true : ( ch: char; attr: byte );
  42.              false: ( x: integer );
  43.            end;
  44.  
  45.   AddrType = record {used in peek and poke routines}
  46.            case integer of
  47.          1: (r, s: integer); {seg and ofs values}
  48.          2: (x: ^integer);
  49.          3: (b: ^byte);
  50.            end;
  51.  
  52.   ScreenType = record {used in saving and copying screens}
  53.          width, size: integer;
  54.          pntr: AddrType;
  55.            end; {ScreenType}
  56.  
  57.  
  58. VAR
  59.   VideoMethod : VideoMethods; {initialized from "environment"}
  60.   VidPtr : AddrType; {used for DMA video}
  61.   MonoBdInstalled : boolean;
  62.   PresentTextMode : sc_AttributeSet;
  63.   PresentForeGround, PresentBackGround : integer;
  64.     {To be used with Turbo's predefined color constants;
  65.     see Turbo Pascal version 3.0 manual at 161}
  66.   PresentScreenMode : sc_ScreenMode;
  67.   AnsiInitKey : integer;
  68.   sc_Maxcol, sc_MaxRow: integer;
  69.     {We make these variables because they're capable of
  70.     changing under software control.}
  71.   NominalCol, NominalRow: integer;
  72.     {We update these variables every time the cursor might
  73.     move under ROM or ANSI but not under DMA.}
  74.  
  75.  
  76. PROCEDURE sc_WriteStr( TheStr : dos2str80 );
  77. VAR
  78.   rgstr : RegisterRecord;
  79. BEGIN
  80.   insert( #27'[', TheStr, 1 );
  81.   WITH rgstr DO BEGIN
  82.     bx := 1; {sends all output to the screen}
  83.     cx := ord( TheStr[0] );
  84.     ds := seg( TheStr );
  85.     dx := ofs( TheStr ) + 1;
  86.     ah := $40;  {Write to a file or device command}
  87.   END; {WITH rgstr}
  88.   msdos( rgstr );
  89. END;  {sc_WriteStr}
  90.  
  91.  
  92.  
  93. PROCEDURE CheckAnsiInitKey;
  94.     {A prompt for the programmer, to be deleted when
  95.     a program is complete.}
  96. BEGIN {CheckAnsiInitKey}
  97.     {4536 is an arbitrarily chosen value.}
  98.   IF AnsiInitKey <> 4536 THEN
  99.     abort('Please initialize with InitAnsiStuf.');
  100. END; {CheckAnsiInitKey}
  101.  
  102.  
  103.  
  104.  PROCEDURE ReadWithoutEcho( VAR thestr : dos2str255 );
  105. CONST backspace = 8;
  106.  
  107.   FUNCTION inkey: CHAR;
  108.   VAR rgstr : RegisterRecord;
  109.   BEGIN {inkey}
  110.     REPEAT
  111.       rgstr.ah := 8;
  112.     {Non-echoing input from standard input device.}
  113.       msdos( rgstr );
  114.     UNTIL rgstr.al in [ backspace, 13, 32..127 ];
  115.     {Means that only backspace, return, and printable
  116.     characters will be recognized in ReadWithoutEcho.}
  117.     inkey := chr(rgstr.al);
  118.   END;  {inkey}
  119.  
  120. VAR bufch : CHAR;
  121. BEGIN  {ReadWithoutEcho}
  122.   thestr := null;
  123.   REPEAT
  124.     bufch := inkey;
  125.     IF (bufch >= ' ') AND (bufch <= '~') THEN
  126.       AddStr( thestr, bufch )
  127.     ELSE
  128.       IF (bufch = CHR( backspace )) AND ( length(TheStr) > 0 )
  129.     THEN TheStr[0] := pred( TheStr[0] );
  130.   UNTIL (bufch = CHR( 13 )) OR
  131.     (length(thestr) >= (sizeof( thestr ) - 1) );
  132. END; {ReadWithoutEcho} 
  133.  
  134.  
  135.  
  136. PROCEDURE sc_CursorPosition( VAR column, row: INTEGER );
  137. label EndProcedure;
  138. TYPE str8 = string[8];
  139. VAR
  140.   ResultCode : INTEGER;
  141.   rowstr, colstr, cpr : str8;
  142.   rgstr: RegisterRecord;
  143. BEGIN
  144.   if VideoMethod <> ANSI then
  145.     begin
  146.       rgstr.ah := 3; {get cursor position}
  147.       rgstr.bh := 0; {specifies display page}
  148.       intr( $10, rgstr );
  149.       column := rgstr.dl + 1;
  150.       row := rgstr.dh + 1;
  151.       goto EndProcedure;
  152.     end;
  153.  
  154.   sc_WriteStr( '6n' );
  155.       {The "Device Status Report" command.  See PC-DOS v2.0
  156.       manual at 13-5.}
  157.   ReadWithoutEcho( cpr );
  158.   WHILE ( cpr[ 1 ] = chr( 27 ) )
  159.     OR
  160.     ( cpr[ 1 ] = '[' ) do delete( cpr, 1, 1 );
  161.   val( copy(cpr,1,2), row, ResultCode );
  162.   IF ResultCode <> 0
  163.     THEN abort( cpr );
  164.   val( copy(cpr,4,2), column, ResultCode );
  165.   IF ResultCode <> 0
  166.     THEN abort( cpr );
  167.   EndProcedure:
  168. END; {sc_CursorPosition}
  169.  
  170.  
  171. function Between( min, x, max: integer ): integer;
  172. begin {Between}
  173.   if x < min then Between := min
  174.   else if x > max then Between := max
  175.        else Between := x;
  176. end; {Between}
  177.  
  178.  
  179.   PROCEDURE sc_GotoXY(column, row: INTEGER);
  180.     {Same as Turbo's GotoXY.}
  181.   var rgstr: RegisterRecord;
  182.   BEGIN {sc_GotoXY}
  183.     if VideoMethod = ANSI then
  184.       sc_WriteStr( concat(IntStr(row, 0),';',
  185.                   IntStr(column, 0),'H') )
  186.     else
  187.       with rgstr do begin
  188.         ah := 2; {set-cursor-position function}
  189.         bh := 0; {specifies display page}
  190.         dh := Between( 0, row - 1, sc_MaxRow - 1 );  
  191.         dl := Between( 0, column - 1, sc_MaxCol - 1 );
  192.         intr( $10, rgstr );
  193.       end;
  194.   END;  {sc_GotoXY}
  195.  
  196.  
  197.   PROCEDURE sc_left;
  198.     {Moves the cursor one space left.}
  199.   var col, row: integer;
  200.   BEGIN
  201.     if VideoMethod = ANSI then
  202.       sc_WriteStr( '1D' )
  203.     else begin
  204.       sc_CursorPosition( Col, Row );
  205.       Col := Col - 1;
  206.       gotoxy( Col, Row );
  207.     end;
  208.   END; {sc_left}
  209.  
  210.   PROCEDURE sc_right;
  211.     {Moves the cursor one space right.}
  212.   var col, row: integer;
  213.   BEGIN
  214.     if VideoMethod = ANSI then
  215.       sc_WriteStr( '1C' )
  216.     else begin
  217.       sc_CursorPosition( Col, Row );
  218.       Col := Col + 1;
  219.       gotoxy( Col, Row );
  220.     end;
  221.   END; {sc_right}
  222.  
  223.   PROCEDURE sc_up;
  224.     {Moves the cursor one row up.}
  225.   var col, row: integer;
  226.   BEGIN
  227.     if VideoMethod = ANSI then
  228.       sc_WriteStr( '1A' )
  229.     else begin
  230.       sc_CursorPosition( Col, Row );
  231.       Row := Row - 1;
  232.       gotoxy( Col, Row );
  233.     end;
  234.   END; {sc_up}
  235.  
  236.   PROCEDURE sc_down;
  237.     {Moves the cursor one row down.}
  238.   var col, row: integer;
  239.   BEGIN
  240.     if VideoMethod = ANSI then
  241.       sc_WriteStr( '1B' )
  242.     else begin
  243.       sc_CursorPosition( Col, Row );
  244.       Row := Row + 1;
  245.       gotoxy( Col, Row );
  246.     end;
  247.   END; {sc_down}
  248.  
  249.  
  250. procedure MonoAttrsToColor( AttrSet: sc_AttributeSet;
  251.                     var foreground, background: integer );
  252. label EndProcedure;
  253. begin {MonoAttrsToColor}
  254.   foreground := PresentForeGround;
  255.   background := PresentBackGround;
  256.   if invisible in AttrSet then begin
  257.     foreground := black;
  258.     background := black;
  259.     goto EndProcedure;
  260.   end;
  261.   if plain in AttrSet then begin
  262.     foreground := LightGray;
  263.     background := black;
  264.     goto EndProcedure;
  265.   end;
  266.   if underscored in AttrSet then begin
  267.     foreground := blue;
  268.     background := black;
  269.   end;
  270.   if ReverseVideo in AttrSet then begin
  271.     foreground := black;
  272.     background := LightGray;
  273.   end;
  274.   if bold in AttrSet then
  275.     if PresentForeGround < DarkGray then
  276.       foreground := PresentForeGround + DarkGray;
  277.   if blinking in AttrSet then
  278.     if VideoMethod <> DMA then begin
  279.       if PresentForeGround < blink then
  280.        foreground := PresentForeGround + blink;
  281.     end
  282.     else
  283.       if PresentBackGround < (blink div 2) then
  284.         background := PresentBackGround + (blink div 2);
  285.   EndProcedure:
  286. end; {MonoAttrsToColor}
  287.  
  288.  
  289. procedure ColorToMonoAttrs( foreground, background : integer;
  290.                    var AttrSet: sc_AttributeSet );
  291. BEGIN {ColorToMonoAttrs}
  292.   AttrSet := [plain];
  293.   if (VideoMethod <> DMA) then 
  294.     begin
  295.       if (foreground >= blink) then begin
  296.         AttrSet := [blinking];
  297.         foreground := foreground - blink
  298.       end;
  299.     end
  300.   else
  301.     if (background >= (blink div 2)) then begin
  302.       AttrSet := [blinking];
  303.       background := background - (blink div 2)
  304.     end;
  305.   if foreground >= DarkGray then begin
  306.     AttrSet := AttrSet + [bold];
  307.     foreground := foreground - DarkGray;
  308.   end;
  309.   case background of
  310.     black : if foreground = blue then
  311.           AttrSet := AttrSet + [underscored]
  312.         else
  313.           if foreground = black then
  314.         AttrSet := [invisible];
  315.     LightGray : if foreground = black then
  316.           AttrSet := AttrSet + [ReverseVideo];
  317.     else begin end;
  318.   end;
  319.   if AttrSet <> [plain] then
  320.     AttrSet := AttrSet - [plain];
  321. end; {ColorToMonoAttrs}
  322.  
  323.  
  324. PROCEDURE sc_TextColor( foreground, background : integer );
  325. BEGIN {sc_TextColor}
  326.   CheckAnsiInitKey;
  327.   IF foreground <> PresentForeGround THEN
  328.     CASE VideoMethod of
  329.       ANSI : sc_WriteStr( IntStr( foreground + 30, 2) + 'm' );
  330.       ROM: TextColor( foreground );
  331.       DMA: BEGIN END;
  332.     END
  333.   else PresentForeGround := foreground;
  334.  
  335.   IF background <> PresentBackGround THEN
  336.     CASE VideoMethod of
  337.       ANSI: sc_WriteStr( IntStr( foreground + 40, 2) +  'm' );
  338.       ROM: TextBackground( background );
  339.       DMA: BEGIN END;
  340.     END
  341.   else PresentBackGround := background;
  342.  
  343.   ColorToMonoAttrs( foreground, background, PresentTextMode );
  344. END; {sc_TextColor}
  345.  
  346.  
  347.  
  348. PROCEDURE sc_TextMode( attribute : sc_TextAttribute );
  349.  
  350.   FUNCTION UpdateNeeded( attribute: sc_TextAttribute ): BOOLEAN;
  351.   BEGIN {UpdateNeeded}
  352.     UpdateNeeded := false;
  353.     IF attribute = plain THEN
  354.       begin
  355.     IF PresentTextMode <> [plain] THEN
  356.       UpdateNeeded := true;
  357.     PresentTextMode := [plain];
  358.       end
  359.     ELSE
  360.       IF not (attribute in PresentTextMode) THEN BEGIN
  361.     PresentTextMode := PresentTextMode + [attribute] - [plain];
  362.     UpdateNeeded := true;
  363.       END;
  364.   END; {UpdateNeeded}
  365.  
  366. VAR fground, bground: INTEGER;
  367. BEGIN
  368.   CheckAnsiInitKey;
  369.  
  370.   IF UpdateNeeded( attribute ) THEN
  371.     if VideoMethod = ANSI then
  372.       begin
  373. (*  IF (attribute in [underscored, ReverseVideo]) and
  374.        (WhereX = 1) THEN
  375.       abort('WARNING:  default background may change.');
  376. Reinsert if you encounter this problem in ANSI mode. *)
  377.         CASE Attribute OF
  378.           plain        : sc_WriteStr( '0m' );
  379.           bold         : sc_WriteStr( '1m' );
  380.           underscored  : sc_WriteStr( '4m' );
  381.           blinking     : sc_WriteStr( '5m' );
  382.           ReverseVideo : sc_WriteStr( '7m' );
  383.           invisible    : sc_WriteStr( '8m' );
  384.         END {CASE}
  385.       end
  386.     else
  387.       begin
  388.         MonoAttrsToColor( PresentTextMode, fground, bground );
  389.         sc_TextColor( fground, bground );
  390.       end;
  391.         MonoAttrsToColor( PresentTextMode,
  392.               PresentForeGround,
  393.               PresentBackGround );
  394. END;  {sc_TextMode}
  395.  
  396.  
  397. PROCEDURE sc_ScrnMode( TheMode: sc_ScreenMode );
  398. BEGIN {sc_ScrnMode}
  399.   CheckAnsiInitKey;
  400.   IF TheMode <> PresentScreenMode THEN
  401.     BEGIN
  402.       if VideoMethod = ANSI then
  403.     sc_WriteStr( '=' + IntStr(ord(TheMode),1) +  'h' )
  404.       else
  405.     if TheMode <= Color80x25 then
  406.       TextMode( ord(TheMode) )
  407.     else
  408.       case TheMode of
  409.         color320 : GraphColorMode;
  410.         BW320 : GraphMode;
  411.         BW640 : begin
  412.                   HiRes;
  413.                   HiResColor( ord(PresentForeGround) );
  414.                 end;
  415.       end; {case}
  416.       PresentScreenMode := TheMode;
  417.     END;
  418. END; {sc_ScrnMode}
  419.  
  420.  
  421. function PeekWord( segm, offs: integer ): integer;
  422. var TmpPtr: AddrType;
  423. begin {PeekWord}
  424.   TmpPtr.s := segm;
  425.   TmpPtr.r := offs;
  426.   PeekWord := TmpPtr.x^;
  427. end; {PeekWord}
  428.  
  429.  
  430. procedure PokeWord( TheWord: integer; segm, offs: integer );
  431. var TmpPtr: AddrType;
  432. begin {PokeWord}
  433.   TmpPtr.s := segm;
  434.   TmpPtr.r := offs;
  435.   TmpPtr.x^ := TheWord;
  436. end; {PokeWord}
  437.  
  438.  
  439. function PeekByte( segm, offs: integer ): byte;
  440. var TmpPtr: AddrType;
  441. begin {PeekByte}
  442.   TmpPtr.s := segm;
  443.   TmpPtr.r := offs;
  444.   PeekByte := TmpPtr.b^;
  445. end; {PeekByte}
  446.  
  447.  
  448. procedure PokeByte( TheByte: byte; segm, offs: integer );
  449. var TmpPtr: AddrType;
  450. begin {PokeByte}
  451.   TmpPtr.s := segm;
  452.   TmpPtr.r := offs;
  453.   TmpPtr.b^ := TheByte;
  454. end; {PokeByte}
  455.  
  456. function ShiftL( TheNum, places: integer ): integer;
  457. begin {ShiftL}
  458.   ShiftL := TheNum shl places;
  459.     {We do this to insulate Turbo's non-standard
  460.     syntax so the code will work with other compilers.
  461.     You may have to rewrite shl using multiplication.}
  462. end; {ShiftL}
  463.  
  464.  
  465. function coord( ColNum, RowNum: byte ): integer;
  466.     {Makes it easier to work with the routines below, which
  467.     treat the screen as a linear sequence of 4000 bytes.}
  468. begin {coord}
  469.   coord := Between(0, RowNum - 1, sc_MaxRow - 1) * sc_MaxCol +
  470.        Between(1, ColNum, sc_MaxCol);
  471. end; {coord}
  472.  
  473.  
  474. procedure ReadVidCh( spot: integer;
  475.              var TheChar: VideoMemChar );
  476. var rgstr: RegisterRecord;
  477. begin {ReadVidCh}
  478.   NominalCol := spot mod sc_MaxCol;
  479.   NominalRow := (spot div sc_MaxCol) + 1;
  480.   case VideoMethod of
  481.     DMA: TheChar.x := PeekWord( VidPtr.s,
  482.                         VidPtr.r + (spot * 2) - 2 );
  483.     ROM: begin
  484.       gotoxy( NominalCol, NominalRow );
  485.       with rgstr do begin
  486.         ah := 8; {reads char and attribute at cursor position}
  487.         bx := 0; {specifies the display page}
  488.         intr( $10, rgstr );
  489.         TheChar.ch := chr( al );
  490.         TheChar.attr := ah;
  491.       end; {with rgstr}
  492.     end;
  493.     {We don't have an else because no PC/MS-DOS screen-reading
  494.     function exists.}
  495.   end; {case}
  496. end; {ReadVidCh}
  497.  
  498.  
  499. procedure WriteVidCh( spot: integer;
  500.              TheChar: VideoMemChar );
  501. var rgstr: RegisterRecord;
  502. begin {WriteVidCh}
  503.   NominalCol := spot mod sc_MaxCol;
  504.   NominalRow := (spot div sc_MaxCol) + 1;
  505.   case VideoMethod of
  506.     DMA: PokeWord( TheChar.x,
  507.            VidPtr.s,
  508.            VidPtr.r + (spot * 2) - 2 );
  509.     ROM: begin
  510.       gotoxy( NominalCol, NominalRow );
  511.       with rgstr do begin
  512.         ah := 9; {write char and attribute}
  513.         bh := 0; {display page}
  514.         cx := 1; {number of chars to write}
  515.         al := ord(TheChar.ch);
  516.         bl := TheChar.attr;
  517.         intr( $10, rgstr );
  518.       end; {with}
  519.     end; {ROM}
  520.     else begin
  521.       sc_gotoxy( NominalCol, NominalRow );
  522.       WriteStr( outp, TheChar.ch );
  523.     end;
  524.   end; {case}
  525. end; {WriteVidCh}
  526.  
  527.  
  528. function RealVideoMode: sc_ScreenMode;
  529. var rgstr: RegisterRecord;
  530. begin {RealVideoMode}
  531.   MonoBdInstalled := false;
  532.   with rgstr do begin
  533.     ah := 15; {function that reads current video mode}
  534.     intr( $10, rgstr ); {performs an Interrupt 10H }
  535.     case al of
  536.       0: RealVideoMode := BW40x25;
  537.       1: RealVideoMode := Color40x25;
  538.       2: RealVideoMode := BW80x25;
  539.       3: RealVideoMode := Color80x25;
  540.       4: RealVideoMode := Color320;
  541.       5: RealVideoMode := BW320;
  542.       6: RealVideoMode := BW640;
  543.       7: begin
  544.        RealVideoMode := BW80x25;
  545.        MonoBdInstalled := true;
  546.      end;
  547.       else abort( 'Mode unknown to ANSI.SYS.' );
  548.     end; {case}
  549.     sc_MaxCol := ah;
  550.     sc_MaxRow := 25;
  551.   end; {with rgstr}
  552. end; {RealVideoMode}
  553.  
  554.  
  555. procedure WriteAt( ColNum, RowNum: byte; TheStr: dos2str255 );
  556. var
  557.   BufChar: VideoMemChar;
  558.   VidMemSpot: integer;
  559.   endstr, cnt : byte;
  560. begin {WriteAt}
  561.   CheckAnsiInitKey;
  562.   endstr := length( TheStr );
  563.   NominalCol := ColNum + endstr;
  564.   NominalRow := RowNum;
  565.   case VideoMethod of
  566.     DMA:
  567.       begin
  568.         BufChar.attr := PresentForeGround or
  569.                     ShiftL(PresentBackGround, 4);
  570.         VidMemSpot := coord( ColNum, RowNum );
  571.         for cnt := 1 to endstr do begin
  572.           BufChar.ch := TheStr[ cnt ];
  573.           PokeWord( BufChar.x, VidPtr.s,
  574.                 (VidMemSpot + cnt - 1) * 2 - 2 );
  575.         end; {for}
  576.       end; {DMA}
  577.     ROM :
  578.       begin
  579.         gotoxy( ColNum, RowNum );
  580.         write( TheStr );
  581.       end; {ROM}
  582.     ANSI :
  583.       begin
  584.         sc_gotoxy( ColNum, RowNum );
  585.         WriteStr( outp, TheStr );
  586.       end;
  587.   end; {case}
  588. end; {WriteAt}
  589.  
  590.  
  591. procedure CursorHeight( lines: byte );
  592. label EndProcedure;
  593. var rgstr: RegisterRecord;
  594. begin {CursorHeight}
  595.   if VideoMethod = ANSI then goto EndProcedure;
  596.   with rgstr do begin
  597.     ah := 1; {set-cursor-type function}
  598.     if MonoBdInstalled then
  599.       cl := 13 {monochrome bd's cursor has 13 lines, maximum}
  600.     else cl := 7; {color bd's has 7}
  601.     if lines = 0 then
  602.       ch := 32  {turns off cursor}
  603.     else if lines > 13 then
  604.        ch := lines
  605.      else ch := cl - lines + 1;
  606.     intr( $10, rgstr );
  607.   end; {with rgstr}
  608.   EndProcedure:
  609. end; {CursorHeight}
  610.  
  611.  
  612. var SavedCol, SavedRow: integer;
  613.  
  614.   PROCEDURE sc_SaveCursorPosition;
  615.     {For temporary storage of a cursor position.}
  616.   BEGIN {sc_SaveCursorPosition}
  617.     if VideoMethod = ANSI then
  618.       sc_WriteStr( 's' )
  619.     else
  620.       sc_CursorPosition( SavedCol, SavedRow );
  621.   END; {sc_SaveCursorPosition}
  622.  
  623.   PROCEDURE sc_RestoreCursorPosition;
  624.   BEGIN {sc_RestoreCursorPosition}
  625.     if VideoMethod = ANSI then
  626.       sc_WriteStr( 'u' )
  627.     else
  628.       gotoxy( SavedCol, SavedRow );
  629.   END; {sc_RestoreCursorPosition}
  630.  
  631.  
  632. PROCEDURE sc_ClrPart( col1, row1, col2, row2: integer );
  633. VAR
  634.   horizdistance, vertdistance, VertCnt : INTEGER;
  635.   clearstring : dos2str255;
  636.   rgstr : RegisterRecord;
  637. BEGIN  {sc_ClrPart}
  638.   if VideoMethod = ANSI then
  639.     begin
  640.       horizdistance := Between( 0, col2 - col1 + 1, sc_MaxCol );
  641.       vertdistance := Between( 0, row2 - row1 + 1, sc_MaxRow );
  642.       fillchar( clearstring, horizdistance + 1, ' ' );
  643.       clearstring[ 0 ] := chr(horizdistance);
  644.       for VertCnt := 0 to vertdistance DO BEGIN
  645.         sc_GotoXY( col1, row1 + VertCnt );
  646.         WriteStr( outp, clearstring );
  647.       END;  {FOR}
  648.     end
  649.   else {VideoMethod = ROM or DMA}
  650.     with rgstr do begin
  651.       ah := 6; {scroll active page up function}
  652.       al := 0; {means blank entire window}
  653.       ch := row1 - 1; cl := col1 - 1;
  654.       dh := row2 - 1; dl := col2 - 1;
  655.       bh := PresentForeGround or ShiftL(PresentBackGround, 4);
  656.       intr( $10, rgstr );
  657.     end; {with}
  658.   sc_gotoxy( col1, row1 );
  659. END;  {sc_ClrPart}
  660.  
  661.  
  662.   PROCEDURE sc_ClrScr;
  663.     {Clears the screen and sends the cursor to the top left
  664.     corner.}
  665.   BEGIN
  666.     if VideoMethod = ANSI then
  667.       sc_WriteStr( '2J' )
  668.     else
  669.       sc_ClrPart( 1,1, sc_MaxCol,sc_MaxRow );
  670.   END; {sc_ClrScr}
  671.  
  672.   PROCEDURE sc_ClrEol(column,row:INTEGER);
  673.   BEGIN  {sc_ClrEol}
  674.     sc_GotoXY( column, row );
  675.     if VideoMethod = ANSI then
  676.       sc_WriteStr( 'K' )
  677.     {The PC-DOS v2.0 manual erroneously lists a lower case k
  678.     for this function.}
  679.     else
  680.       sc_ClrPart( column,row, sc_MaxCol,row );
  681.   END;  {sc_ClrEol}
  682.  
  683. PROCEDURE sc_scrollwindow( col1, row1, col2, row2, lines: integer );
  684. VAR
  685.   rgstr : RegisterRecord;
  686. BEGIN  {sc_scrollwindow}
  687.   if VideoMethod = ANSI then abort(
  688. 'Before restarting this program type: set videomethod=dma')
  689.   else {VideoMethod = ROM or DMA}
  690.   IF lines <> 0 THEN
  691.   BEGIN
  692.     with rgstr do begin
  693.       IF lines < 0 then ah := 7 {scroll active page down function}
  694.         ELSE ah := 6; {scroll up}
  695.       al := abs(lines); {no. of lines to scroll}
  696.       ch := row1 - 1; cl := col1 - 1;
  697.       dh := row2 - 1; dl := col2 - 1;
  698.       bh := PresentForeGround or ShiftL(PresentBackGround, 4);
  699.       intr( $10, rgstr );
  700.     end; {with}
  701.   END; {IF lines <> 0}
  702. END;  {sc_scrollwindow}
  703.  
  704. procedure ScrnSave( var scrn: ScreenType;
  705.             col1, row1, col2, row2: integer );
  706. var
  707.   cnt, row, col: integer;
  708.   BufCh: VideoMemChar;
  709. begin {ScrnSave}
  710.   if VideoMethod = ROM then
  711.     begin
  712.       CursorHeight(0); {turns off cursor}
  713.       sc_SaveCursorPosition;
  714.     end;
  715.   with scrn do begin
  716.     width := Between( 1, col2 - col1 + 1, sc_MaxCol );
  717.     size := width * Between( 1, row2 - row1 + 1, sc_MaxRow ) * 2;
  718.     {It's *2 to make room for attribute bytes.}
  719.     if (MaxAvail * 16.0) < (1.0 * size) then
  720.       abort( 'Too little memory to save screen.' );
  721.     GetMem( pntr.x, size );
  722.     cnt := 0;
  723.     for row := row1 to row2 do begin
  724.       for col := col1 to col2 do begin
  725.     ReadVidCh( coord(col, row), BufCh );
  726.     PokeWord( BufCh.x, pntr.s, pntr.r + cnt );
  727.     cnt := cnt + 2;
  728.       end; {for col}
  729.     end; {for row}
  730.   end; {with}
  731.   if VideoMethod = ROM then
  732.     begin
  733.       CursorHeight(2); {restores cursor}
  734.       sc_RestoreCursorPosition;
  735.     end;
  736. end; {ScrnSave}
  737.  
  738.  
  739. procedure ScrnRestore( scrn: ScreenType; col, row: integer );
  740. var
  741.   x, y, cnt: integer;
  742.   BufCh: VideoMemChar;
  743. begin {ScrnRestore}
  744.   if VideoMethod = ROM then
  745.     begin
  746.       CursorHeight(0); {turns off cursor}
  747.       sc_SaveCursorPosition;
  748.     end;
  749.   with scrn do begin
  750.     cnt := 0;
  751.     while cnt < size do begin    
  752.       BufCh.x := PeekWord( pntr.s, pntr.r + cnt );
  753.       x := ((cnt div 2) mod width) + col;
  754.       y := ((cnt div 2) div width) + row;
  755.       if (x <= sc_MaxCol) and (y <= sc_MaxRow) then
  756.     WriteVidCh( (y - 1) * sc_MaxCol + x, BufCh );
  757.       cnt := cnt + 2;
  758.     end; {for}
  759.     FreeMem( pntr.x, size );
  760.   end; {with}
  761.   if VideoMethod = ROM then
  762.     begin
  763.       CursorHeight(2); {restores cursor}
  764.       sc_RestoreCursorPosition;
  765.     end;
  766. end; {ScrnRestore}
  767.  
  768.  
  769. PROCEDURE ReassignKey( KeyCode: INTEGER;
  770.                Extended: BOOLEAN;
  771.                NewDefn: dos2str80 );
  772. BEGIN {ReassignKey}
  773.   IF Extended
  774.     THEN sc_WriteStr( '0;' + IntStr( KeyCode, 0 ) +
  775.               ';' + NewDefn + 'p' )
  776.     ELSE sc_WriteStr( IntStr( KeyCode, 0 ) +
  777.               ';' + NewDefn + 'p' );
  778.     {Doing this independent of ANSI.SYS is too
  779.     difficult.  We leave it unimplemented for
  780.     non-ANSI I/O.}
  781. END; {ReassignKey} 
  782.  
  783.  
  784. procedure ReadEnvironment( name: dos2str80; var parameter: dos2str80 );
  785. var
  786.   bufch : char;
  787.   tmpcopy: dos2str80;
  788.   found: boolean;
  789.   EnvSeg, EnvNdx, cnt, EqSpot: integer;
  790. begin  {ReadEnvironment}
  791.   EnvSeg := PeekWord( Cseg, $2C );
  792.     {Get segment address of the environment from PSP.}
  793.   found := false;
  794.   parameter := null;
  795.   EnvNdx := 0;
  796.   for cnt := 1 to length( name ) do
  797.     name[cnt] := UpCase( name[cnt] );
  798.   repeat
  799.     tmpcopy := null;
  800.     bufch := chr( PeekByte(EnvSeg, EnvNdx) );
  801.     while bufch <> chr(0) do begin
  802.       AddStr( tmpcopy, UpCase( bufch ) );
  803.       EnvNdx := EnvNdx + 1;
  804.       bufch := chr( PeekByte(EnvSeg, EnvNdx) );
  805.     end; {while}
  806.     if pos( name, tmpcopy ) = 1 then
  807.       begin
  808.     EqSpot := pos( '=', tmpcopy );
  809.     if EqSpot > 0 then
  810.       begin
  811.         parameter := copy( tmpcopy,
  812.                        EqSpot + 1,
  813.                        length(tmpcopy) - EqSpot );
  814.         found := true;
  815.       end;
  816.       end;
  817.     EnvNdx := EnvNdx + 1;
  818.     if PeekByte(EnvSeg, EnvNdx) = 0 then
  819.       found := true;
  820.   until found;
  821.   while pos(' ', parameter) = 1 do delete(parameter,1,1);
  822. end; {ReadEnvironment}
  823.  
  824.  
  825. PROCEDURE InitAnsiStuf;
  826. VAR
  827.   setting : dos2str80;
  828. BEGIN {InitAnsiStuf}
  829.   ReadEnvironment( 'VideoMethod', setting );
  830.   if setting = 'DMA' then
  831.     VideoMethod := DMA
  832.   else
  833.     if setting = 'ROM' then
  834.       VideoMethod := ROM
  835.     else
  836.       VideoMethod := ANSI;
  837.  
  838.   PresentForeGround := LightGray;
  839.   PresentBackGround := black;
  840.   PresentTextMode := [plain];
  841.  
  842.   if VideoMethod = ANSI then
  843.     begin
  844.       sc_WriteStr( '0m' ); {sets text mode to plain}
  845.       PresentScreenMode := BW80x25;
  846.       sc_MaxCol := 80;
  847.       sc_MaxRow := 25;
  848.     end
  849.   else
  850.     begin
  851.       LowVideo;
  852.       TextColor( LightGray );
  853.       TextBackGround( black );
  854.     {We have to set these colors so that AnsiStuf variables
  855.     will be able to track text attributes and prevent
  856.     needless interrupts.}
  857.       PresentScreenMode := RealVideoMode;
  858.       if MonoBdInstalled then
  859.     VidPtr.s := MonoBdAddr
  860.       else
  861.     VidPtr.s := GrafBdAddr;
  862.       VidPtr.r := 0;
  863.     end;
  864.   AnsiInitKey := 4536; {an arbitrarily chosen value}
  865. END; {InitAnsiStuf}
  866. 
  867.